//
// Created by F1997 on 2024/10/21.
//

#ifndef NETWORK_TRAFFIC_PROCESSING_PCAPUTILS_H
#define NETWORK_TRAFFIC_PROCESSING_PCAPUTILS_H
#include "pch.h"
#include "../main/CompareTraffic.h"
#include "IniReader.h"

class PcapUtils {
public:
    PcapUtils() = default;

    // 列表初始化和优化，{}还是()???
    PcapUtils(std::shared_ptr<spdlog::logger> _my_logger ) //, IniReader* _iniCfg, CompareTraffic _compareTraffic)
    //: my_logger(_my_logger), iniCfg(_iniCfg)
    //compareTraffic(_compareTraffic)
    {
        my_logger = _my_logger;
        //iniCfg = _iniCfg;
        //compareTraffic = new CompareTraffic(iniCfg);
    };

    void readSocket();
    void readPcapFile();

    bool checkIsStart(std::chrono::system_clock::time_point startTime, int offset);

    int readNetworkIfaceLine1(std::chrono::system_clock::time_point startTime, IniReader* iniCfg);
    int readNetworkIfaceLine2(std::chrono::system_clock::time_point startTime, IniReader* iniCfg);

    int readNetworkIface2();
    int readNetworkIface();
    int readNetworkInterface();

    int readNetworkIface4();
    int readMsg(std::shared_ptr<spdlog::logger> my_logger, IniReader* iniCfg);
    int sampled(std::shared_ptr<spdlog::logger> _my_logger, IniReader* iniCfg);

    std::chrono::system_clock::time_point parseTime(const std::string& timeStr);
    std::chrono::system_clock::time_point string_to_time_point(const std::string& str);

    void parse_packet(const struct pcap_pkthdr* pkthdr, const u_char* packet);

    void packet_handler2(const struct pcap_pkthdr *pkthdr, const u_char *packet);
    void packet_handler3(const struct pcap_pkthdr *pkthdr, const u_char *packet);

    void handleTcp(const struct pcap_pkthdr *pkthdr, const u_char *packet);
    void handleUdp(const struct pcap_pkthdr *pkthdr, const u_char *packet);
    void printPacket(const u_char *packet, int payload_size, int payload_offset);

    // 解析协议栈的回调
    static void packet_handler4(u_char *user_data, const struct pcap_pkthdr *pkthdr, const u_char *packet);
    int packet_handler4Main();

private:
    // 流量对比类
    CompareTraffic compareTraffic;
    std::shared_ptr<spdlog::logger> my_logger;

    // pcap 文件开始的24个字节
    struct PcapFileHeader // sizeof 字节数：24
    {
        uint32_t magic; // 0xa1b2c3d4 //
        uint16_t version_major;
        uint16_t version_minor;
        int32_t thiszone;  // gmt to local correction / 格林尼治至本地校正，时区修正
        uint32_t sigfigs;  // accuracy of timestamps / 精确时间戳
        uint32_t snaplen;  // max length saved portion of each pkt / 抓包的最大长度
        uint32_t linktype; // data link type (LINKTYPE_*) / 数据链路类型（LINKTYPE *）
    };


    // 结构体是由pcap_loop自己填充的，用来取得一些关于数据包的信息
    struct my_pcap_pkthdr {
        struct timeval ts;   /* 时间戳 */
        bpf_u_int32 caplen;   /* 已捕获部分的长度 */
        bpf_u_int32 len;  /* 该包的脱机长度 */
    };

    // 定义以太网头部结构
    struct my_ether_header {
        u_int8_t ether_dhost[6]; // 目的MAC地址
        u_int8_t ether_shost[6]; // 源MAC地址
        u_int16_t ether_type;    // 协议类型
    };

    // 定义IP头部结构
    struct my_ip_header {
        u_int8_t ip_hl : 4, ip_v : 4; // IP头部长度和版本
        u_int8_t ip_tos;              // 服务类型
        u_int16_t ip_len;             // 总长度
        u_int16_t ip_id;              // 标识
        u_int16_t ip_off;             // 标志和段偏移
        u_int8_t ip_ttl;              // 生存时间
        u_int8_t ip_p;                // 协议
        u_int16_t ip_sum;             // 校验和
        struct in_addr ip_src;        // 源IP地址
        struct in_addr ip_dst;        // 目的IP地址
    };

    // 定义TCP头部结构
    struct my_tcp_header {
        u_int16_t th_sport;           // 源端口
        u_int16_t th_dport;           // 目的端口
        u_int32_t th_seq;             // 序列号
        u_int32_t th_ack;             // 确认号
        u_int8_t th_off : 4, th_x2 : 4; // 数据偏移和保留位
        u_int8_t th_flags;            // 标志
        u_int16_t th_win;             // 窗口大小
        u_int16_t th_sum;             // 校验和
        u_int16_t th_urp;             // 紧急指针
    };

    // udp 头部
    struct my_udp_header // udp报头
    {
        unsigned short uh_srcport; // 源端口
        unsigned short uh_dstport; // 目的端口
        unsigned short uh_len; // 数据长度
        unsigned short uh_chk; // 校验和，检查位
    };

    // 郑州5档行情
    typedef struct
    {
        unsigned char 	Flag;					//协议标志
        char 			TypeID;					//协议版本
        unsigned short  Length;					//包长度
        unsigned short	PacketNo;				//全0
        unsigned int	ChangeNo;				//增量编号
        short			InstrumentNo;			//合约编码
        char			InstrumentID[10];		//合约
        unsigned int	UpdateTime;				//最后更新时间(秒)
        unsigned short	UpdateMillisec;			//最后更新时间(毫秒)
        int				Volume;
        int				OpenInterest;
        int				BidVolume1;
        int				BidVolume2;
        int				BidVolume3;
        int				BidVolume4;
        int				BidVolume5;
        int				AskVolume1;
        int				AskVolume2;
        int				AskVolume3;
        int				AskVolume4;
        int				AskVolume5;
        double			LastPrice;
        double			BidPrice1;
        double			BidPrice2;
        double			BidPrice3;
        double			BidPrice4;
        double			BidPrice5;
        double			AskPrice1;
        double			AskPrice2;
        double			AskPrice3;
        double			AskPrice4;
        double			AskPrice5;
        double			Turnover;
    }Zbp05; // 5档行情

    // udp报文
    typedef struct
    {
        my_ether_header EthHead;
        my_ip_header IpHead;
        my_udp_header UdpHead;
        Zbp05 AmgBody;
    }Zbp05Udp; // udp报文

    // 域结构体，4字节
    struct domain_s {
        int16_t FieldID;
        int16_t FieldSize;
    };


    // MIRP报文头，24字节，如果MIRP报文被加密，指的是仅MIRP报文体部分被加密。⽤户在收到MIRP报文时可分析报文头来有选择地进⾏报文解密
    struct MIRP_Header {
        u_int8_t Flag;
        int8_t TypeID;
        u_int16_t Length;
        int32_t PacketNo;
        int16_t TopicID;
        u_int16_t SnapMillisec;
        int32_t SnapNo;
        u_int32_t SnapTime;
        int16_t CommPhaseNo;
        int8_t CenterChangeNo;
        int8_t Reserved;
    };

    // MDQP 报文头，8字节
    struct MDQPHeader {
        uint8_t flag;
        int8_t typeID;
        uint16_t length;
        uint32_t requestID;

        void parse(const char* data) {
            flag = static_cast<uint8_t>(data[0]);
            typeID = static_cast<int8_t>(data[1]);
            length = ntohs(*reinterpret_cast<const uint16_t*>(data + 2));
            requestID = ntohl(*reinterpret_cast<const uint32_t*>(data + 4));
        }
    };

    // MIRP 报文头，24字节
    struct MIRPHeader {
        uint8_t flag;
        int8_t typeID;
        uint16_t length;
        uint32_t packetNo;
        uint16_t topicID;
        uint16_t snapMillisec;
        uint32_t snapNo;
        uint32_t snapTime;
        uint16_t commPhaseNo;
        uint8_t centerChangeNo;
        uint8_t reserved;

        void parse(const char* data) {
            flag = static_cast<uint8_t>(data[0]);
            typeID = static_cast<int8_t>(data[1]);
            length = ntohs(*reinterpret_cast<const uint16_t*>(data + 2));
            packetNo = ntohl(*reinterpret_cast<const uint32_t*>(data + 4));
            topicID = ntohs(*reinterpret_cast<const uint16_t*>(data + 8));
            snapMillisec = ntohs(*reinterpret_cast<const uint16_t*>(data + 10));
            snapNo = ntohl(*reinterpret_cast<const uint32_t*>(data + 12));
            snapTime = ntohl(*reinterpret_cast<const uint32_t*>(data + 16));
            commPhaseNo = ntohs(*reinterpret_cast<const uint16_t*>(data + 20));
            centerChangeNo = static_cast<uint8_t>(data[22]);
            reserved = static_cast<uint8_t>(data[23]);
        }
    };

};


#endif //NETWORK_TRAFFIC_PROCESSING_PCAPUTILS_H
